<template>
  <div class="code-editor" :class="{ 'code-editor--readonly': readonly }">
    <!-- 顶部操作栏 -->
    <div class="code-toolbar">
      <el-tooltip
        effect="dark"
        :content="wrapEnabled ? '取消自动换行' : '自动换行'"
        placement="bottom"
      >
        <el-button
          type="text"
          size="mini"
          @click="toggleWrap"
        >
          <i :class="!wrapEnabled ? 'iconfont icon-wenbenhuanhang' : 'iconfont icon-buhuanhang'" />
        </el-button>
      </el-tooltip>
      <el-tooltip effect="dark" content="复制" placement="bottom">
        <el-button
          type="text"
          size="mini"
          @click="copyContent"
        >
          <i class="iconfont icon-fuzhi" />
        </el-button>
      </el-tooltip>

      <el-tooltip effect="dark" content="清空" placement="bottom">
        <el-button
          v-if="clearable && content && !readonly"
          type="text"
          size="mini"
          @click="clearContent"
        >
          <i class="iconfont icon-qingkong" />
        </el-button>
      </el-tooltip>
    </div>

    <!-- 行号 + 代码编辑区域 -->
    <div class="code-body" :style="{ height: contentHeight + 'px' }">
      <!-- 行号区域 -->
      <div
        ref="lineNumbers"
        class="line-numbers"
      >
        <div
          v-for="(line, index) in lines"
          :key="index"
          class="line-number"
          :style="{ height: lineHeights[index] + 'px' }"
        >
          {{ index + 1 }}
        </div>
      </div>

      <!-- 代码编辑区 -->
      <div class="code-container">
        <textarea
          ref="editor"
          class="code-content"
          :placeholder="placeholder"
          :readonly="readonly"
          :value="value"
          :style="{
            lineHeight: lineHeight + 'px',
            whiteSpace: wrapEnabled ? 'pre-wrap' : 'pre'
          }"
          @input="$emit('input', $event.target.value)"
          @scroll="syncScroll"
          @paste="handlePaste"
          @drop="handleDrop"
        />

        <!-- 隐藏的测量元素 -->
        <pre
          ref="measure"
          class="measure-element"
          :style="{
            lineHeight: lineHeight + 'px',
            whiteSpace: wrapEnabled ? 'pre-wrap' : 'pre',
            width: contentWidth + 'px',
            fontFamily: 'monospace', // 新增：确保字体一致
            fontSize: '14px' // 新增：确保字号一致
          }"
        >{{ content }}</pre>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    // 绑定值，支持v-model和:value+@input
    value: {
      type: String,
      default: ''
    },
    // 显示行数，控制编辑器高度
    rows: {
      type: Number,
      default: 10
    },
    // 行高
    lineHeight: {
      type: Number,
      default: 20
    },
    // 是否可清空
    clearable: {
      type: Boolean,
      default: false
    },
    // 占位文本
    placeholder: {
      type: String,
      default: ''
    },
    // 是否只读
    readonly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      wrapEnabled: false, // 是否自动换行
      lines: [], // 文本行数组
      lineHeights: [], // 每行高度
      contentWidth: 0 // 内容区宽度
    }
  },
  computed: {
    // 当前内容
    content() {
      return this.value
    },
    // 计算内容区域高度
    contentHeight() {
      return this.rows * this.lineHeight + 16 // 16px是内边距
    }
  },
  watch: {
    // 内容变化时更新行高
    value: {
      handler() {
        this.$nextTick(this.updateLineHeights)
      },
      immediate: true // 新增
    },
    // 窗口大小变化时重新计算
    '$refs.editor.clientWidth'() {
      this.$nextTick(this.updateLineHeights)
    },
    // 新增：自动换行状态变化时重新计算
    wrapEnabled() {
      this.$nextTick(this.updateLineHeights)
    }
  },
  mounted() {
    // 初始化设置
    if (this.$refs.editor) {
      this.$refs.editor.wrap = this.wrapEnabled ? 'soft' : 'off'
      // 修改：用setTimeout确保DOM完全渲染
      setTimeout(() => {
        this.contentWidth = this.$refs.editor.clientWidth - 16
        this.updateLineHeights()
      }, 0)
    }

    // 新增：监听窗口大小变化
    window.addEventListener('resize', () => {
      this.$nextTick(this.updateLineHeights)
    })
  },
  // 新增：销毁时移除事件监听
  beforeDestroy() {
    window.removeEventListener('resize', this.updateLineHeights)
  },
  methods: {
    // 切换自动换行
    toggleWrap() {
      this.wrapEnabled = !this.wrapEnabled
      this.$refs.editor.wrap = this.wrapEnabled ? 'soft' : 'off'
      this.$nextTick(this.updateLineHeights)
    },

    // 更新行高计算
    updateLineHeights() {
      if (!this.$refs.measure || !this.$refs.editor) return

      // 新增：统一处理换行符（兼容不同来源内容）
      const content = this.content?.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
      this.lines = content ? content.split('\n') : ['']

      // 优化：确保内容区宽度正确
      this.contentWidth = this.$refs.editor.clientWidth - 16
      if (this.contentWidth <= 0) { // 新增：容错处理
        this.contentWidth = this.$refs.editor.offsetWidth - 16
      }

      const measure = this.$refs.measure
      measure.textContent = '' // 清空测量元素（原先是设置innerHTML）

      const lineHeights = []

      this.lines.forEach((line) => {
        const temp = document.createElement('div')
        // 新增：确保测量元素字体样式与编辑器一致
        temp.style.fontFamily = 'monospace'
        temp.style.fontSize = '14px'
        temp.textContent = line || ' ' // 处理空行
        measure.appendChild(temp)

        // 新增：确保高度不小于设置的行高
        const height = temp.offsetHeight
        lineHeights.push(Math.max(height, this.lineHeight))

        measure.removeChild(temp)
      })

      this.lineHeights = lineHeights
      this.$nextTick(this.syncScroll)
    },

    // 处理粘贴事件
    handlePaste(e) {
      if (this.readonly) {
        e.preventDefault()
        return
      }
      e.preventDefault()
      const plainText = (e.clipboardData || window.clipboardData).getData('text/plain') || ''

      const textarea = this.$refs.editor
      if (!textarea) return

      const start = textarea.selectionStart
      const end = textarea.selectionEnd
      const newValue =
        this.content.substring(0, start) +
        plainText +
        this.content.substring(end)

      this.$emit('input', newValue)

      this.$nextTick(() => {
        textarea.selectionStart = textarea.selectionEnd = start + plainText.length
        this.updateLineHeights()
      })
    },

    // 处理拖放事件
    handleDrop(e) {
      if (this.readonly) {
        e.preventDefault()
      }
    },

    // 同步滚动位置
    syncScroll() {
      const textarea = this.$refs.editor
      const lineNumbers = this.$refs.lineNumbers
      if (textarea && lineNumbers) {
        lineNumbers.scrollTop = textarea.scrollTop
      }
    },

    // 复制内容到剪贴板
    copyContent() {
      navigator.clipboard.writeText(this.content).then(() => {
        this.$message.success('复制成功')
      }).catch(err => {
        this.$message.error('复制失败：' + err)
      })
    },

    // 清空内容
    clearContent() {
      this.$emit('input', '')
    }
  }
}
</script>

<style scoped>
.code-editor {
  display: flex;
  flex-direction: column;
  border: 1px solid #dcdcdc;
  border-radius: 4px;
  font-family: monospace;
  font-size: 14px;
  overflow: hidden;
}

.code-editor--readonly {
  background-color: #f5f7fa;
}

.code-toolbar {
  display: flex;
  gap: 4px;
  justify-content: flex-end;
  padding: 0 8px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}

.clear-btn {
  color: #f56c6c;
}

.clear-btn:hover {
  background-color: #fef0f0;
  color: #f56c6c;
}

.code-body {
  display: flex;
  overflow: hidden;
}

/* 行号区域样式 */
.line-numbers {
  background-color: #f5f7fa;
  color: #909399;
  padding: 8px 4px;
  text-align: right;
  user-select: none;
  min-width: 30px;
  border-right: 1px solid #e4e7ed;
  overflow: hidden; /* 隐藏行号区域滚动条 */
  box-sizing: border-box;
}

/* 行号样式 - 确保显示 */
.line-number {
  padding: 1px 4px 4px;
  white-space: nowrap;
  font-size: 10px;
  box-sizing: border-box;
  display: flex;
  align-items: flex-start; /* 保持顶部对齐，但通过padding-top微调 */
  justify-content: flex-end;
  min-height: 1em;
  margin-top: 0; /* 确保无额外上边距 */
  line-height: inherit; /* 继承行高，与内容保持一致 */
}

.code-container {
  flex: 1;
  position: relative;
  overflow: hidden;
}

/* 代码编辑区样式 */
.code-content {
  width: 100%;
  height: 100%;
  padding: 7px 8px;
  border: none;
  outline: none;
  resize: none;
  box-sizing: border-box;
  overflow: auto; /* 仅内容区显示滚动条 */
  font-family: inherit;
  font-size: inherit;
  background-color: transparent;
}

/* 优化滚动条样式 */
.code-content::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.code-content::-webkit-scrollbar-thumb {
  background-color: #ccc;
  border-radius: 4px;
}

.code-content::-webkit-scrollbar-track {
  background-color: #f5f5f5;
}

/* 只读模式样式 */
.code-editor--readonly .code-content {
  background-color: #fff;
  cursor: not-allowed;
  color: #606266;
}

/* 测量元素 - 用于计算行高 */
.measure-element {
  position: absolute;
  top: -9999px;
  left: 0;
  margin: 0;
  padding: 0;
  font-family: inherit;
  font-size: inherit;
  visibility: hidden;
  pointer-events: none;
  /* 新增：确保换行计算一致 */
  word-break: normal;
  word-wrap: normal;
}
</style>
